package world.criver.mm_vworld_server.function;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import world.criver.crc.CRC;
import world.criver.mm_vworld_server.config.conConfig;
import world.criver.mm_vworld_server.data.daSave;
import world.criver.mm_vworld_server.data.daServer;

import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Enumeration;

@Component
public class funUDP {
    @Autowired
    private conConfig conConfig;

    private DatagramSocket socket;
    private DatagramSocket socketLocal;
    private ArrayList<InetAddress> nets;
    private DatagramPacket packet;
    private DatagramPacket packetLocal;
    private byte[] bs;
    private String message;

    public boolean broadcast(){
        try{
            iniInet();
            iniAutoUdp();
            iniLocalUdp();
            message="ip="+InetAddress.getLocalHost().getHostAddress()+"&port="+conConfig.getServerPort()
                    +"&name="+ Base64.getEncoder().encodeToString(daSave.properties.getName().getBytes(StandardCharsets.UTF_8))+"&openPassword="+daSave.properties.isPasswordTestOpen()+"&openCommand="+daSave.properties.isCommandOpen()
                    +"&nowPlayerNum="+ daServer.clients.size()+"&maxPlayerNum="+daSave.properties.getMaxOnlineNum()+"&version="+daSave.version
                    +"&content="+Base64.getEncoder().encodeToString(daSave.properties.getContent().getBytes(StandardCharsets.UTF_8))+"&dateTime="+daSave.dateTime.getYear()+"年"+daSave.dateTime.getMonth()+"月"+daSave.dateTime.getDate()+"日"
                    +"&avatar="+daSave.avatar.getAvatarHairNum()+","+daSave.avatar.getAvatarHairColor()+","+daSave.avatar.getAvatarBodyNum()+","+daSave.avatar.getAvatarBodyColor()+","
                        +daSave.avatar.getAvatarEyeNum()+","+daSave.avatar.getAvatarEyeColor()+","+daSave.avatar.getAvatarClothsNum()+","+daSave.avatar.getAvatarClothsColor()
                    +"&timestamp="+System.currentTimeMillis();
//            System.out.println("发送UDP："+message);
            message="MMV"+new CRC().encrypt(conConfig.getEncryptKey(), message);
            bs=message.getBytes(StandardCharsets.UTF_8);
            for(InetAddress inet:nets){
                packet=new DatagramPacket(bs,bs.length,inet, conConfig.getBroadcastPort());
                packetLocal=new DatagramPacket(bs,bs.length,inet, conConfig.getBroadcastPort()+1);
                socket.send(packet);
                socketLocal.send(packetLocal);
            }
//            socket.close();
//            System.out.println("发送成功："+System.currentTimeMillis());
            return true;
        }catch (Exception e){
            e.printStackTrace();
            socket.close();
            return false;
        }
    }
    private void iniAutoUdp(){
        try {
            if (socket == null || socket.isClosed()) {
                socket = new DatagramSocket();
                socket.setBroadcast(true);
                socket.setReuseAddress(true);
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    private void iniLocalUdp(){
        try {
            if (socketLocal == null || socketLocal.isClosed()) {
                socketLocal = new DatagramSocket();
                socketLocal.setBroadcast(true);
                socketLocal.setReuseAddress(true);
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    private void iniInet(){
        if(nets!=null&&!nets.isEmpty())return;
        try {
            nets = new ArrayList<>();
            Enumeration<NetworkInterface> ints = NetworkInterface.getNetworkInterfaces();
            while (ints.hasMoreElements()) {
                NetworkInterface intf = ints.nextElement();
                Enumeration<InetAddress> addrs = intf.getInetAddresses();
                while (addrs.hasMoreElements()) {
                    InetAddress addr = addrs.nextElement();
                    if (addr instanceof Inet4Address) {
                        String[] q = addr.getHostAddress().split("\\.");
                        nets.add(InetAddress.getByName(q[0] + "." + q[1] + "." + q[2] + ".255"));
                    }
                }
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    public void close(){
        if(socket!=null && !socket.isClosed())socket.close();
        if(socketLocal!=null && !socketLocal.isClosed())socketLocal.close();
    }
}
